/**
 * @FileName: WhieCardController.java
 * @Author
 * @Description:
 * @Date 2016年1月4日 下午2:11:46
 * @CopyRight ZTE Corporation
 */
package cn.hpclub.server.controller.admin;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.commons.lang.StringUtils;
import org.apache.poi.EncryptedDocumentException;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.poifs.filesystem.OfficeXmlFileException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.jfinal.plugin.activerecord.Page;
import com.jfinal.render.JsonRender;

import cn.hpclub.server.model.Blankcard;
import cn.hpclub.server.model.Organization;
import cn.hpclub.server.service.BlankcardService;
import cn.hpclub.server.util.excel.ExcelLogs;
import cn.hpclub.server.util.excel.ExcelUtil;

public class BlankcardController extends BaseAdminController<Blankcard>{
    private static final String URL_TEMPLATE  = "/template/admin/file/白卡导入模版-大掌柜.xls";

    private static final int    MAX_ADD_COUNT = 8;
    private static final int    MAX_NUM_CODE  = 20;
    private static final String ORG_LIST      = "orgList";
    private static final String ADD_NUM       = "add_num";
    private static final String ORG_NAME      = "org_name";
    private static final String ORG_ID        = "org_id";
    private static final String NUMBER_CODE   = "number_code";
    private static Logger       log           = LoggerFactory.getLogger(BlankcardController.class);

    /**
     * @Title: 获取白卡列表
     */
    public void list(){
        int defaultOrgId = initOrgTree();
        ConcurrentHashMap<String, String> searchInfo = getSearchInfo();
        if(searchInfo.get(ORG_ID) == null){
            searchInfo.put(ORG_ID, String.valueOf(defaultOrgId));
        }
        log.debug("BlankCardController.list");
        findByPageBySearchInfo(searchInfo);
        setAttrs(searchInfo);
        render("/admin/blankcard_list.tpl");
    }

    /**
     * @Title: update
     * @Description:修改白卡数量void
     */
    public void update(){
        int orgId = getParaToInt(ORG_ID);
        int addNum = getParaToInt(ADD_NUM);
        int totalNum = Blankcard.dao.getTotalSimCardNum(orgId);
        int usedNum = Blankcard.dao.getUsedSimCardCount(orgId);
        if(validateAddNum(addNum, totalNum, usedNum)){
            if(updateSimCardNumber(orgId, (totalNum + addNum))){
                renderJson(new JSONObject().put("status", 200).put("message", "更改白卡数量成功！")
                        .put("total_num", (totalNum + addNum)).put("available_num", (totalNum + addNum - usedNum))
                        .toString());
            } else{
                renderJson(new JSONObject().put("status", 500).put("message", "操作失败，服务器内部错误！").toString());
            }
        } else{
            renderJson(new JSONObject().put("status", 400).put("message", "操作失败，参数错误！").toString());
        }
    }

    /**
     * @Title: upload
     * @Description:白卡变更数据导入 void
     */
    public void upload(){
        String result = null;
        int status = 1;
        try{
            result = importBlankcardData();
        }
        catch(OfficeXmlFileException | EncryptedDocumentException | InvalidFormatException e){
            e.printStackTrace();
            result = "格式错误，请上传excel 2003/2007格式文件";
            status = 0;
        }
        catch(Exception e){
            e.printStackTrace();
            result = "导入数据失败,请联系管理员";
            status = 0;
        }
        finally{
            Map<String, Object> jsonMap = new HashMap<String, Object>();
            jsonMap.put("status", status);
            jsonMap.put("result", result);
            render(new JsonRender(jsonMap).forIE());
        }
    }

    /**
     * @Title: importBlankcardData
     * @Description:导入数据
     * @param successCount
     * @param errorMsg
     * @throws FileNotFoundException
     *             void
     * @throws InvalidFormatException
     * @throws EncryptedDocumentException
     */

    private String importBlankcardData()
            throws FileNotFoundException, EncryptedDocumentException, InvalidFormatException{
        int successCount = 0;
        String errorMsg = "";
        InputStream inputStream = new FileInputStream(getFile().getFile());
        ExcelLogs logs = new ExcelLogs();
        Collection<Map> importExcel = ExcelUtil.importExcel(Map.class, inputStream, "yyyy/MM/dd HH:mm:ss", logs, 0);
        int i = 1;
        for(Map<?, ?> m : importExcel){
            String itemErrorMsg = saveorUpdateData(m, i);
            log.debug("itemErrorMsg=" + itemErrorMsg);
            if(itemErrorMsg == null){
                successCount++;
            } else{
                errorMsg += itemErrorMsg;
            }
            i++;
        }
        int failedCount = importExcel.size() - successCount;
        if((failedCount > 0) && (errorMsg.length() > 200)){
            errorMsg = errorMsg.substring(0, 200) + "\r\n。。。。。。";
        }
        return "成功：" + successCount + "条," + "失败：" + failedCount + "条。" + (failedCount > 0 ? errorMsg : "");
    }

    public void template(){
        renderFile(URL_TEMPLATE);
    }

    /**
     * @Title: saveorUpdateData
     * @Description:将一条excel数据解析保存到数据。
     * @param data，一条excel数据
     * @param i，第几条，用于合成errormsg
     * @return String 保存成功，返回null。保存失败，返回errorMsg.
     */
    private String saveorUpdateData(Map<?, ?> data, int i){
        String prefix = "\r\n第" + i + "条：";
        if(!validImportExcelCellData(data)){
            return prefix + "渠道编码、变更数量不能为空";
        }
        String numCode = getString(ExcelUtil.removeSpace(String.valueOf(data.get("渠道编码"))), MAX_NUM_CODE);
        int simCardCount;
        try{
            int addCount = Integer.parseInt(getString(String.valueOf(data.get("变更数量")), MAX_ADD_COUNT));
            simCardCount = Blankcard.dao.getSimCardCountByNumCode(numCode);
            int totalCount = addCount + simCardCount;
            if(totalCount < 0){
                return prefix + "渠道编码" + numCode + " 变更数量（" + addCount + "）大于总量（" + simCardCount + "）";
            }
            if(!Blankcard.dao.updateSimCardCountByNumCode(numCode, totalCount)){
                return prefix + "渠道编码" + numCode + " 更新失败";
            }
        }
        catch(IOException e){
            return prefix + "渠道编码" + numCode + " 对应机构不存在";
        }
        catch(NumberFormatException e){
            return prefix + "渠道编码" + numCode + " 变更数量非法：" + String.valueOf(data.get("变更数量"));
        }
        return null;
    }

    private String getString(String fullString, int maxLen){
        if(StringUtils.isBlank(fullString) || "null".equalsIgnoreCase(fullString) || fullString.length() > maxLen){
            return "";
        }
        return fullString;
    }

    private boolean validImportExcelCellData(Map<?, ?> data){
        String numberCode = String.valueOf(data.get("渠道编码"));
        String changeCount = String.valueOf(data.get("变更数量"));
        if(StringUtils.isBlank(numberCode) || "null".equalsIgnoreCase(numberCode) || StringUtils.isBlank(changeCount)
                || "null".equalsIgnoreCase(changeCount)){
            log.error("validImportExcelCellData data error");
            return false;
        }
        return true;
    }

    /**
     * @Title: updateSimCardNumber
     * @Description:更新白卡数量
     * @param orgid
     *            机构ID
     * @param number
     *            新增白卡数量
     * @return boolean 操作结果
     */
    private boolean updateSimCardNumber(int orgid, int number){
        Organization role = getModel(Organization.class);
        role.set("id", orgid);
        role.set("SIMCardCount", number);
        return role.update();
    }

    /**
     * @Title: validateAddNum
     * @Description:校验新增白卡数量
     * @param addNum
     *            新增白卡数量
     * @param totalNum
     *            白卡总数量
     * @param usedNum
     *            已使用白卡数量
     * @return boolean 新增白卡数量是否合法: true 合法，false非法
     */
    private boolean validateAddNum(int addNum, int totalNum, int usedNum){
        return (totalNum - usedNum + addNum) >= 0;
    }

    /**
     * @Title: initOrgTree
     * @Description:初始化机构树列表
     * @return int 返回默认查询机构ID
     */
    /*
     * private int initOrgTree(){ List<Entry<String, String>> orgList =
     * InterfaceUtil.getOrgList(); if(orgList.size() > 0){ 机构树可用
     * setAttr(ORG_LIST, orgList); return
     * Integer.parseInt(orgList.get(0).getValue()); } else{ return 0; } }
     */

    /**
     * @Title:findByPageBySearchInfo
     * @Description:根据查询条件，获取白卡列表 void
     */
    private void findByPageBySearchInfo(ConcurrentHashMap<String, String> searchInfo){
        long start = System.currentTimeMillis();
        int pageNumber = getParaToInt(PAGE_NUMBER, 1);
        int pageSize = getParaToInt(PAGE_SIZE, 10);
        String sqlEx = getSqlExtFromSearchInfo(searchInfo);
        int orgId = Integer.parseInt(searchInfo.get(ORG_ID));

        Page<Blankcard> pager = BlankcardService.findBlankcardByPage(pageNumber, pageSize, orgId, sqlEx,
                                                                     "org.id as orgId, DisplayName, SIMCardCount",
                                                                     "ORDER BY SIMCardCount DESC, orgId ASC");

        log.info("search use time:" + (System.currentTimeMillis() - start));
        setAttr(PAGER, pager);
    }

    /**
     * @Title: getSqlExtFromSearchInfo
     * @Description:获取查询条件
     * @return String
     */
    private String getSqlExtFromSearchInfo(ConcurrentHashMap<String, String> searchInfo){
        String sqlEx = "";
        for(Entry<String, String> item : searchInfo.entrySet()){
            if(item.getKey().equals(ORG_NAME)){
                sqlEx += " and DisplayName like '%" + item.getValue() + "%'";
            } else if(item.getKey().equals(NUMBER_CODE)){
                sqlEx += " and NumCode like '%" + item.getValue() + "%'";
            }
        }
        return sqlEx;
    }

}
